package com.uinnova.product.eam.web.oauth.mvc;

import com.binary.framework.util.ControllerUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;


/**
 * 获取 登录令牌
 */
@Slf4j
@Controller
@RequestMapping("/eam/oauth")
public class OauthMvc {

    @Value("${oauth.server.url}")
	private String urlOauth;

    // 设置全局 cookie
	private CookieStore cookieStore = new BasicCookieStore();

	// 设置全局 httpclient
	private CloseableHttpClient httpclient = HttpClients.createDefault();

	/**
	 * 根据用户名密码获取 Authorization 访问令牌
	 * @param request
	 * @param response
	 * @param param
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping("/getTokenByLoginInfo")
	public void getTokenByLoginInfo(HttpServletRequest request, HttpServletResponse response, @RequestBody Map<String, String> param) throws ServletException, IOException {
		Map<String, String> data = new HashMap<>();		// 返回结果
		String firstLocation = this.backgroundLogin(param);
		String secondLocation = this.firstRedirest(firstLocation);
		String thirdLocation = this.secondRedirest(secondLocation);
		String authorizationUrl = this.thirdRedirest(thirdLocation);
		// 跳转地址截取token
		String[] strings = StringUtils.substringsBetween(authorizationUrl, "tk=", "&");
		data.put("Authorization", "Bearer " + strings[0]);
		ControllerUtils.returnJson(request, response, data);
	}


	/**
	 * 后台登录 路径为：oauth 服务中的配置地址 + /login
	 * @param param
	 * @return
	 */
    public String backgroundLogin(Map<String, String> param) {
		HttpClientContext context = HttpClientContext.create();
		context.setCookieStore(cookieStore);
		HttpPost httpPost = new HttpPost(urlOauth + "/login");

		CloseableHttpResponse response;
		String location = null;
		try {
			List<BasicNameValuePair> pair =new ArrayList<>();
			// 遍历map 将数据转化为我们的表单数据
			for (Map.Entry<String,String> entry: param.entrySet()) {
				pair.add(new BasicNameValuePair(entry.getKey(),entry.getValue()));
			}
			//http post 中放入我们的经过url编码的表单参数
			httpPost.setEntity(new UrlEncodedFormEntity(pair));
			response = httpclient.execute(httpPost, context);
			int responseCode = response.getStatusLine().getStatusCode();
			if (responseCode == 302 || responseCode == 303) {
				Header locationHeader = response.getFirstHeader("Location");
				location = locationHeader.getValue();
			}
		}catch(IOException e){
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		log.info("oauth_first_redirect_location:" + location);
		return location;
	}


	/**
	 * 第一次重定向地址
	 * @param url
	 * @return
	 */
	public String firstRedirest(String url) {
		HttpClientContext context = HttpClientContext.create();
		context.setCookieStore(cookieStore);
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response;
		String location = null;
		try(CloseableHttpClient httpClient = HttpClients.createDefault()) {
			response = httpClient.execute(httpPost, context);
			int responseCode = response.getStatusLine().getStatusCode();
			if (responseCode == 302 || responseCode == 303) {
				Header locationHeader = response.getFirstHeader("Location");
				location = locationHeader.getValue();
			}
		} catch(Exception e){
			e.printStackTrace();
		}
		return location;
	}


	/**
	 * 第二次重定向
	 * @param url
	 * @return
	 */
	public String secondRedirest(String url) {
		RequestConfig config = RequestConfig.custom().setRedirectsEnabled(false).build();// 允许重定向
		CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(config).setDefaultCookieStore(cookieStore).build();
		String location = null;
		int responseCode = 0;

		HttpResponse response;
		try {
			response = httpClient.execute(new HttpGet(url));
			responseCode = response.getStatusLine().getStatusCode();
			if (responseCode == 302 || responseCode == 303) {
				Header locationHeader = response.getFirstHeader("Location");
				location = locationHeader.getValue();
			}
		} catch (Exception e) {

			e.printStackTrace();
		}
		return location;
	}


	/**
	 * 第三次重定向获取令牌
	 * @param url
	 * @return
	 */
	public String thirdRedirest(String url) {
		RequestConfig config = RequestConfig.custom().setRedirectsEnabled(false).build();// 允许重定向
		CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(config).setDefaultCookieStore(cookieStore).build();
		String location = null;
		int responseCode = 0;

		HttpResponse response;
		try {
			response = httpClient.execute(new HttpGet(url));
			responseCode = response.getStatusLine().getStatusCode();
			if (responseCode == 302 || responseCode == 303) {
				Header locationHeader = response.getFirstHeader("Location");
				location = locationHeader.getValue();
			}
		} catch (Exception e) {

			e.printStackTrace();
		}
		return location;
	}

}
